package chaincode

import (
	"fmt"
	"os"
	"strings"

	"github.com/facebookgo/inject"
	"github.com/hyperledger/fabric-contract-api-go/contractapi"
	assetapi "github.com/hyperledger/fabric-samples/asset-kx/chaincode-go/chaincode/asset/api"
	assetService "github.com/hyperledger/fabric-samples/asset-kx/chaincode-go/chaincode/asset/service"
	assetloanapi "github.com/hyperledger/fabric-samples/asset-kx/chaincode-go/chaincode/assetloan/api"
	assetLoanService "github.com/hyperledger/fabric-samples/asset-kx/chaincode-go/chaincode/assetloan/service"
	assetruleapi "github.com/hyperledger/fabric-samples/asset-kx/chaincode-go/chaincode/assetrule/api"
	assetRuleService "github.com/hyperledger/fabric-samples/asset-kx/chaincode-go/chaincode/assetrule/service"
	ledgerapi "github.com/hyperledger/fabric-samples/asset-kx/chaincode-go/chaincode/ledger-api"
	"github.com/hyperledger/fabric-samples/asset-kx/chaincode-go/chaincode/support"
)

type SmartContract struct {
	contractapi.Contract
	assetapi.AssetContractApi         `inject:"AssetContractApi"`
	assetloanapi.AssetLoanContractApi `inject:"AssetLoanContractApi"`
	assetruleapi.AssetRuleContractApi `inject:"AssetRuleContractApi"`
}

func NewSmartContract() *SmartContract {
	var g inject.Graph
	sc := &SmartContract{}
	SmartAssetContract := &assetService.SmartAssetContract{}
	SmartAssetLoanContract := &assetLoanService.SmartAssetLoanContract{}
	SmartAssetRuleContract := &assetRuleService.SmartAssetRuleContract{}
	AssetRuleSupport := &assetRuleService.AssetRuleSupport{}
	err := g.Provide(
		&inject.Object{Value: sc},
		&inject.Object{Value: SmartAssetContract, Name: "AssetContractApi"},
		&inject.Object{Value: SmartAssetLoanContract, Name: "AssetLoanContractApi"},
		&inject.Object{Value: SmartAssetRuleContract, Name: "AssetRuleContractApi"},
		&inject.Object{Value: AssetRuleSupport, Name: "AssetRuleSupportApi"},
	)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	if err := g.Populate(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	sc.TransactionContextHandler = new(ledgerapi.TransactionContext)
	return sc
}

//assetNos: 以英文“,”分隔的字符串
func (s *SmartContract) ReadAssets(ctx ledgerapi.TransactionContextInterface, assetNos string) ([]interface{}, error) {
	assetNoArr := strings.Split(assetNos, ",")
	assets, err := s.AssetContractApi.ReadAssets(ctx, assetNoArr...)
	if err != nil {
		return nil, err
	}
	return support.ToAssetInterfaces(assets), nil
}

//assetNos: 以英文“,”分隔的字符串
func (s *SmartContract) DelAssets(ctx ledgerapi.TransactionContextInterface, assetNos string) error {
	assetNoArr := strings.Split(assetNos, ",")
	return s.AssetContractApi.DelAssets(ctx, assetNoArr...)
}

//当资产不存在时，返回错误
func (s *SmartContract) ReadAsset(ctx ledgerapi.TransactionContextInterface, assetNo string) (interface{}, error) {
	return s.AssetContractApi.ReadAsset(ctx, assetNo)
}

func (s *SmartContract) ReadLoanRelatedAssets(ctx ledgerapi.TransactionContextInterface, loanNo string) ([] interface{}, error) {
	assets, err := s.AssetLoanContractApi.ReadLoanRelatedAssets(ctx, loanNo)
	if err != nil {
		return nil, err
	}
	return support.ToAssetInterfaces(assets), nil
}
